﻿using MySqlConnector;
using Rocket.API;
using Rocket.API.Collections;
using Rocket.Core.Plugins;
using Rocket.Unturned;
using Rocket.Unturned.Chat;
using Rocket.Unturned.Commands;
using Rocket.Unturned.Player;
using System;
using System.Collections.Generic;
using UnityEngine;
using Logger = Rocket.Core.Logging.Logger;

namespace MachineBanned
{
    public class MachineBanned : RocketPlugin<MachineBannedConfig>
    {
        public static MachineBanned Instance;
        public IFreeSql Db;

        protected override void Load()
        {
            Instance = this;
            string ConnectionString = $"Data Source={this.Configuration.Instance.DatabaseIP};Port={this.Configuration.Instance.DatabasePort};User ID={this.Configuration.Instance.DatabaseUserName};Password={this.Configuration.Instance.DatabasePassword}; Initial Catalog={this.Configuration.Instance.DatabaseName};Min pool size=16";
            Db = new FreeSql.FreeSqlBuilder()
                .UseConnectionFactory(FreeSql.DataType.CustomMySql, () => new MySqlConnection(ConnectionString))
                .UseAutoSyncStructure(true) //自动同步实体结构到数据库
                .Build(); //请务必定义成 Singleton 单例模式
            Db.SetDbProviderFactory(MySqlConnectorFactory.Instance);

            //Db.Ado.ExecuteCommand($"CREATE TABLE if not exists `{Configuration.Instance.HwidInfoTableName.ToLower()}` (`id` int unsigned primary key auto_increment, `steamid` varchar(255), `hwid` varchar(255), `ip` varchar(255), `display_name` varchar(255), `reason` varchar(255), `create_time` datetime, `banned_time` int)" +
            //    $" CHARACTER SET utf8 COLLATE utf8_general_ci;");
            //Db.Ado.ExecuteCommand($"CREATE TABLE if not exists `{Configuration.Instance.HwidLogTableName.ToLower()}` (`id` int unsigned primary key auto_increment, `ip` varchar(255), `hwid` varchar(255), `steamid` varchar(255), `display_name` varchar(255), `create_time` datetime, `update_time` datetime)" +
            //    $" CHARACTER SET utf8 COLLATE utf8_general_ci;");
            //老框架SqlSugar遗留代码，Freesql不需要

            U.Events.OnPlayerConnected += Events_OnPlayerConnected;
        }

        private void Events_OnPlayerConnected(Rocket.Unturned.Player.UnturnedPlayer player)
        {
            string steamid = player.CSteamID.ToString();
            string ip = player.IP;
            string hwid = System.Convert.ToBase64String(player.SteamPlayer().playerID.hwid);
            string last_displayname = player.DisplayName;
            if (Db.Select<BanInfo>().As(this.Configuration.Instance.HwidInfoTableName).Where(it => it.steamid == steamid).Any())
            {
                var info = Db.Select<BanInfo>().As(this.Configuration.Instance.HwidInfoTableName).Where(it => it.steamid == steamid).OrderByDescending(sc => sc.create_time).First();
                if (info.create_time.AddMinutes(info.banned_time) > DateTime.Now)
                {
                    player.Kick(info.reason);
                    return;
                }
            }
            else if (Db.Select<BanInfo>().As(this.Configuration.Instance.HwidInfoTableName).Where(it => it.hwid == hwid).Any())
            {
                var info = Db.Select<BanInfo>().As(this.Configuration.Instance.HwidInfoTableName).Where(it => it.hwid == hwid).OrderByDescending(sc => sc.create_time).First();
                if (info.create_time.AddMinutes(info.banned_time) > DateTime.Now)
                {
                    player.Kick(info.reason);
                    return;
                }
            }
            else if (Db.Select<BanInfo>().As(this.Configuration.Instance.HwidInfoTableName).Where(it => it.ip == ip).Any())
            {
                var info = Db.Select<BanInfo>().As(this.Configuration.Instance.HwidInfoTableName).Where(it => it.ip == ip).OrderByDescending(sc => sc.create_time).First();
                if (info.create_time.AddMinutes(info.banned_time) > DateTime.Now)
                {
                    player.Kick(info.reason);
                    return;
                }
            }
            if (!Db.Select<HwidLog>().As(this.Configuration.Instance.HwidLogTableName).Where(it => it.steamid == steamid && it.hwid == hwid && it.ip == ip && it.display_name == last_displayname).Any())
            {
                Db.Insert(new HwidLog() { steamid = steamid, hwid = hwid, ip = ip, display_name = last_displayname, create_time = DateTime.Now, update_time = DateTime.Now }).AsTable(this.Configuration.Instance.HwidLogTableName).ExecuteAffrows();
            }
            else
            {
                Db.Update<HwidLog>().AsTable(this.Configuration.Instance.HwidLogTableName).Where(it => it.steamid == steamid && it.hwid == hwid && it.ip == ip && it.display_name == last_displayname).Set(it => new HwidLog() { update_time = DateTime.Now }).ExecuteAffrows();
            }
            Logger.Log($"[极光未来] - 机器码封禁 - 玩家档案更新:{player.CSteamID}/{player.IP}/{System.Convert.ToBase64String(player.SteamPlayer().playerID.hwid)}");
        }

        public override TranslationList DefaultTranslations => new TranslationList()
        {
            {
                "KICK_HWID",
                "你的机器码已被封禁"
            }
        };

        protected override void Unload()
        {
            U.Events.OnPlayerConnected -= Events_OnPlayerConnected;
        }
    }

    public class HwidCommand : IRocketCommand
    {
        public AllowedCaller AllowedCaller => AllowedCaller.Both;

        public string Name => "hwid";

        public string Help => "获取玩家hwid";

        public string Syntax => string.Empty;

        public List<string> Aliases => new List<string>();

        public List<string> Permissions => new List<string>() { "aro.mb.hwid" };

        public void Execute(IRocketPlayer caller, string[] command)
        {
            if (command.Length == 0)
            {
                if (caller is ConsolePlayer)
                {
                    Logger.Log("Please enter the correct format, such as: /hwid player");
                    return;
                }
                UnturnedChat.Say(caller, Convert.ToBase64String((caller as UnturnedPlayer).SteamPlayer().playerID.hwid));
                return;
            }
            if (command.GetUnturnedPlayerParameter(0) != null)
            {
                string csteamid = command.GetUnturnedPlayerParameter(0).CSteamID.ToString();
                var item = MachineBanned.Instance.Db.Select<HwidLog>().As(MachineBanned.Instance.Configuration.Instance.HwidLogTableName).Where(it => it.steamid == csteamid).OrderByDescending(sc => sc.update_time);
                if (item.Any())
                {
                    if (caller is ConsolePlayer) Logger.Log(item.First().hwid);
                    else UnturnedChat.Say(caller, item.First().hwid);
                    return;
                }
                if (caller is ConsolePlayer) Logger.Log("The player could not be found");
                else UnturnedChat.Say(caller, "找不到该玩家", Color.yellow);
                return;
            }
            if (caller is ConsolePlayer) Logger.Log(System.Convert.ToBase64String(command.GetUnturnedPlayerParameter(0).SteamPlayer().playerID.hwid));
            else UnturnedChat.Say(caller, System.Convert.ToBase64String(command.GetUnturnedPlayerParameter(0).SteamPlayer().playerID.hwid));
        }
    }

    public class HwidBanCommand : IRocketCommand
    {
        public AllowedCaller AllowedCaller => AllowedCaller.Both;

        public string Name => "hwidban";

        public string Help => "封禁机器码";

        public string Syntax => string.Empty;

        public List<string> Aliases => new List<string>();

        public List<string> Permissions => new List<string>() { "aro.mb.hwidban" };

        public void Execute(IRocketPlayer caller, string[] command)
        {
            if (command.Length < 1)
            {
                if (caller is ConsolePlayer)
                {
                    Logger.Log("Please enter the correct format, such as: /hwid player");
                    return;
                }
                UnturnedChat.Say(caller, "请输入正确的格式,例如: /hwid 玩家", Color.yellow);
                return;
            }
            if (command[0].Length == 17)
            {
                string csteamid = command[0].ToString();
                var item = MachineBanned.Instance.Db.Select<HwidLog>().As(MachineBanned.Instance.Configuration.Instance.HwidLogTableName).Where(it => it.steamid == csteamid).OrderByDescending(sc => sc.update_time);
                if (!item.Any())
                {
                    if (caller is ConsolePlayer) Logger.Log("The player could not be found");
                    else UnturnedChat.Say(caller, "找不到该玩家", Color.yellow);
                    return;
                }
                else
                {
                    var info = item.First();
                    MachineBanned.Instance.Db.Insert(new BanInfo() { steamid = info.steamid, hwid = info.hwid, ip = info.ip, display_name = info.display_name, create_time = DateTime.Now, reason = (command.Length >= 2) ? command[1] : string.Empty, banned_time = (command.Length >= 3) ? int.Parse(command[2]) : MachineBanned.Instance.Configuration.Instance.DefaultBannedTime }).AsTable(MachineBanned.Instance.Configuration.Instance.HwidInfoTableName).ExecuteAffrows();
                    if (UnturnedPlayer.FromName(command[0]) != null)
                    {
                        UnturnedPlayer.FromName(command[0]).Kick((command.Length >= 2) ? command[1] : MachineBanned.Instance.Translate("KICK_HWID"));
                    }
                    if (caller is ConsolePlayer) Logger.Log("Banned Success");
                    else UnturnedChat.Say(caller, "封禁成功");
                    return;
                }
            }
            else if (command.GetUnturnedPlayerParameter(0) == null)
            {
                if (caller is ConsolePlayer) Logger.Log("The player could not be found");
                else UnturnedChat.Say(caller, "找不到该玩家", Color.yellow);
                return;
            }
            UnturnedPlayer player = command.GetUnturnedPlayerParameter(0);
            string steamid = player.CSteamID.ToString();
            string ip = player.IP;
            string hwid = System.Convert.ToBase64String(player.SteamPlayer().playerID.hwid);
            string last_displayname = player.DisplayName;
            MachineBanned.Instance.Db.Insert(new BanInfo() { steamid = steamid, hwid = hwid, ip = ip, display_name = last_displayname, create_time = DateTime.Now, reason = (command.Length >= 2) ? command[1] : string.Empty, banned_time = (command.Length >= 3) ? int.Parse(command[2]) : MachineBanned.Instance.Configuration.Instance.DefaultBannedTime }).AsTable(MachineBanned.Instance.Configuration.Instance.HwidInfoTableName).ExecuteAffrows();
            player.Kick((command.Length >= 2) ? command[1] : MachineBanned.Instance.Translate("KICK_HWID"));
            if (caller is ConsolePlayer) Logger.Log("Banned Success");
            else UnturnedChat.Say(caller, "封禁成功");
        }
    }
}
